/*!
 * \file WTSCmpHelper.hpp
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief 数据压缩辅助工具，基于zstdlib压缩库
 * 
 * \details 本文件提供了基于ZSTD算法的数据压缩和解压缩功能。
 *          主要特点：
 *          - 高效的ZSTD压缩算法
 *          - 可配置的压缩级别
 *          - 简单易用的静态接口
 *          - 自动内存管理
 *          - 异常安全的错误处理
 *          
 *          ZSTD（Zstandard）是Facebook开发的实时压缩算法，
 *          提供了优秀的压缩比和压缩速度平衡。
 */
#pragma once
#include <string>
#include <stdint.h>

#include "../WTSUtils/zstdlib/zstd.h"

/*!
 * \class WTSCmpHelper
 * \brief WTS数据压缩辅助工具类
 * 
 * \details WTSCmpHelper提供了基于ZSTD算法的数据压缩和解压缩功能。
 *          该类的主要特点：
 *          - 静态方法设计，无需实例化
 *          - 基于ZSTD高性能压缩算法
 *          - 支持可配置的压缩级别（1-22）
 *          - 自动计算压缩缓冲区大小
 *          - 返回std::string便于使用
 *          - 异常安全的错误处理机制
 *          
 *          使用场景：
 *          - 历史数据压缩存储
 *          - 网络传输数据压缩
 *          - 日志文件压缩
 *          - 内存数据压缩
 * 
 * \note 所有方法都是静态方法，不需要创建类实例
 * \see ZSTD压缩库文档
 */
class WTSCmpHelper
{
public:
	/*!
	 * \brief 压缩数据
	 * 
	 * \details 使用ZSTD算法压缩指定的数据块。该方法会：
	 *          1. 根据输入数据大小计算压缩缓冲区大小
	 *          2. 使用指定的压缩级别进行压缩
	 *          3. 调整输出缓冲区到实际压缩后的大小
	 *          4. 返回压缩后的数据
	 *          
	 *          压缩级别说明：
	 *          - 1-3：快速压缩，较低压缩比
	 *          - 4-9：平衡模式，推荐使用
	 *          - 10-22：高压缩比，较慢速度
	 * 
	 * \param data 待压缩的数据指针
	 * \param dataLen 待压缩数据的长度（字节）
	 * \param uLevel 压缩级别（1-22），默认为1
	 * \return std::string 压缩后的数据
	 * 
	 * \note 压缩级别越高，压缩比越好但速度越慢
	 * \warning 输入数据指针不能为空，dataLen必须大于0
	 */
	static std::string compress_data(const void* data, uint32_t dataLen, uint32_t uLevel = 1)
	{
		std::string desBuf;
		// 计算压缩所需的最大缓冲区大小
		std::size_t const desLen = ZSTD_compressBound(dataLen);
		desBuf.resize(desLen, 0);
		
		// 执行压缩操作
		size_t const cSize = ZSTD_compress((void*)desBuf.data(), desLen, data, dataLen, uLevel);
		
		// 调整缓冲区到实际压缩后的大小
		desBuf.resize(cSize);
		return desBuf;
	}

	/*!
	 * \brief 解压缩数据
	 * 
	 * \details 使用ZSTD算法解压缩指定的数据块。该方法会：
	 *          1. 从压缩数据中获取原始数据大小
	 *          2. 分配相应大小的解压缩缓冲区
	 *          3. 执行解压缩操作
	 *          4. 验证解压缩后的数据大小
	 *          5. 返回解压缩后的数据
	 * 
	 * \param data 待解压缩的数据指针
	 * \param dataLen 待解压缩数据的长度（字节）
	 * \return std::string 解压缩后的数据
	 * 
	 * \throws std::runtime_error 当解压缩后的数据大小与预期不符时抛出异常
	 * \note 输入数据必须是有效的ZSTD压缩数据
	 * \warning 输入数据指针不能为空，dataLen必须大于0
	 */
	static std::string uncompress_data(const void* data, uint32_t dataLen)
	{
		std::string desBuf;
		// 获取解压缩后的数据大小
		unsigned long long const desLen = ZSTD_getFrameContentSize(data, dataLen);
		desBuf.resize((std::size_t)desLen, 0);
		
		// 执行解压缩操作
		size_t const dSize = ZSTD_decompress((void*)desBuf.data(), (size_t)desLen, data, dataLen);
		
		// 验证解压缩后的数据大小
		if (dSize != desLen)
			throw std::runtime_error("uncompressed data size does not match calculated data size");
		return desBuf;
	}
};

